/* eslint-disable @typescript-eslint/no-var-requires */
/* eslint-disable no-console */
/* eslint-disable @typescript-eslint/no-unused-vars */
// 先启动后端项目然后 运行package.json的 openapi2ts,就会在client/src下生成api文件夹和能使用的ts文件
// @@umijs/openapi 配置文件是 .openapi2tsrc.ts
const fs = require('fs')
const path = require('path')

// 将字符串转换为驼峰命名
function toCamelCase(str) {
  // 移除/api/前缀
  str = str.replace(/^\/api\//, '')

  // 将路径分隔符和特殊字符转换为驼峰
  return str
    .replace(/[/\-_]/g, ' ')
    .replace(/\s+(\w)/g, (match, char) => char.toUpperCase())
    .replace(/^\w/, (char) => char.toLowerCase())
}

// 生成键名的函数，确保一致性
function generateKeyName(httpMethod, urlPath, params) {
  const baseKey = `${httpMethod}${toCamelCase(urlPath).trim()}`

  if (params.length === 0) {
    return baseKey
  } else if (params.length === 1) {
    const result = `${baseKey}Param0`
    return result
  } else {
    // 对于多个参数，在键名中添加参数标识
    const paramSuffix = params.map((param) => param.charAt(0).toUpperCase() + param.slice(1)).join('')
    const result = `${baseKey}${paramSuffix}`
    return result
  }
}

// 提取HTTP方法名
function extractHttpMethod(functionName) {
  if (functionName.startsWith('get')) return 'get'
  if (functionName.startsWith('post')) return 'post'
  if (functionName.startsWith('put')) return 'put'
  if (functionName.startsWith('delete')) return 'delete'
  if (functionName.startsWith('patch')) return 'patch'
  return 'unknown' // 默认或未知方法
}

// 处理单个文件
function processFile(filePath) {
  try {
    const content = fs.readFileSync(filePath, 'utf8')
    let modified = false

    // 使用更简单的正则表达式匹配request调用
    const requestRegex = /request<[^>]*>\(['"`]([^'"`]+)['"`]/g
    let match
    let newContent = content

    while ((match = requestRegex.exec(content)) !== null) {
      const fullMatch = match[0]
      const url = match[1]

      // 跳过已经处理过的URL（不包含/api/的）
      if (!url.startsWith('/api/')) {
        continue
      }

      // 查找这个request调用所在的函数
      const matchIndex = match.index
      const beforeMatch = content.substring(0, matchIndex)
      const lastFunctionMatch = beforeMatch.match(/export async function (\w+)/g)

      if (lastFunctionMatch && lastFunctionMatch.length > 0) {
        const lastFunction = lastFunctionMatch[lastFunctionMatch.length - 1]
        const functionName = lastFunction.replace('export async function ', '')
        const httpMethod = extractHttpMethod(functionName)

        // 检查函数体中是否使用了param0
        const functionStartIndex = beforeMatch.lastIndexOf('export async function')
        const functionEndIndex = content.indexOf('}', matchIndex)
        const functionBody = content.substring(functionStartIndex, functionEndIndex)

        // 提取所有参数
        const paramMatches = functionBody.match(/param(\d+)/g)
        const params = paramMatches ? [...new Set(paramMatches)].sort() : []

        // 检查原始URL是否包含变量
        const urlHasParams = url.includes('${param')

        let newUrl
        if (urlHasParams && params.length > 0) {
          // 生成新的键名：基于HTTP方法和URL路径，包含参数数量信息
          const urlPath = url.replace(/\/api\//, '').replace(/\$\{param\d+\}/g, '')

          // 使用统一的键名生成函数
          const keyName = generateKeyName(httpMethod, urlPath, params)

          // 生成新的URL：askBIApiUrls.键名(参数)
          const paramString = params.join(',')
          newUrl = `\${askBIApiUrls.${keyName}(${paramString})}`
        } else {
          // 没有变量的URL，使用原来的逻辑
          const camelCaseUrl = toCamelCase(url)
          newUrl = `\${askBIApiUrls.${httpMethod}${camelCaseUrl.charAt(0).toUpperCase() + camelCaseUrl.slice(1)}}`
        }

        // 替换URL并添加注释
        const newRequestCall = fullMatch.replace(url, newUrl)

        // 查找这行代码的完整行，添加注释
        const lines = newContent.split('\n')
        let targetLineIndex = -1

        // 找到包含这个request调用的行
        for (let i = 0; i < lines.length; i++) {
          if (lines[i].includes(fullMatch)) {
            targetLineIndex = i
            break
          }
        }

        if (targetLineIndex !== -1) {
          // 在该行末尾添加注释，如果该行还没有包含原始URL的注释
          const currentLine = lines[targetLineIndex]
          const newRequestLine = currentLine.replace(fullMatch, newRequestCall)

          // 检查是否已经有原始URL注释
          if (!newRequestLine.includes('// 原来的url:')) {
            lines[targetLineIndex] = newRequestLine + ` // 原来的url: ${url}`
          } else {
            lines[targetLineIndex] = newRequestLine
          }

          newContent = lines.join('\n')
        } else {
          newContent = newContent.replace(fullMatch, newRequestCall)
        }

        modified = true
      }
    }

    // 额外处理：将模板字符串中的 ${param0} 格式改成 (param0) 格式
    const templateStringRegex = /`([^`]+)`/g
    let templateMatch
    while ((templateMatch = templateStringRegex.exec(newContent)) !== null) {
      const templateContent = templateMatch[1]
      if (templateContent.includes('${param')) {
        const newTemplateContent = templateContent.replace(/\$\{param(\d+)\}/g, '(param$1)').replace(/\s+\(/g, '(') // 移除参数前的空格
        const oldTemplateString = `\`${templateContent}\``
        const newTemplateString = `\`${newTemplateContent}\`` // 使用反引号

        if (newContent.includes(oldTemplateString)) {
          // 查找包含模板字符串的行并添加注释
          const lines = newContent.split('\n')
          let templateLineIndex = -1

          for (let i = 0; i < lines.length; i++) {
            if (lines[i].includes(oldTemplateString)) {
              templateLineIndex = i
              break
            }
          }

          if (templateLineIndex !== -1) {
            const currentLine = lines[templateLineIndex]
            const newLine = currentLine.replace(oldTemplateString, newTemplateString)

            // 检查是否已经有原始URL注释
            if (!newLine.includes('// 原来的url:')) {
              lines[templateLineIndex] = newLine + ` // 原来的url: ${templateContent}`
            } else {
              lines[templateLineIndex] = newLine
            }

            newContent = lines.join('\n')
          } else {
            newContent = newContent.replace(oldTemplateString, newTemplateString)
          }

          modified = true
        }
      }
    }

    // 额外修复：将单引号改为反引号，并移除参数前的空格
    const singleQuoteRegex = /request<[^>]*>\('([^']+)'/g
    while ((match = singleQuoteRegex.exec(newContent)) !== null) {
      const fullMatch = match[0]
      const url = match[1]

      // 检查是否包含参数，移除参数前的空格
      let newUrl = url
      if (url.includes('(param')) {
        newUrl = url.replace(/\s+\(/g, '(')
      }

      const newRequestCall = fullMatch.replace("'", '`').replace("'", '`')

      // 查找包含这个调用的行并添加注释
      const lines = newContent.split('\n')
      let quoteLineIndex = -1

      for (let i = 0; i < lines.length; i++) {
        if (lines[i].includes(fullMatch)) {
          quoteLineIndex = i
          break
        }
      }

      if (quoteLineIndex !== -1) {
        const currentLine = lines[quoteLineIndex]
        let newLine

        if (newUrl !== url) {
          const finalRequestCall = newRequestCall.replace(url, newUrl)
          newLine = currentLine.replace(fullMatch, finalRequestCall)
        } else {
          newLine = currentLine.replace(fullMatch, newRequestCall)
        }

        // 检查是否已经有原始URL注释，并且这个URL不是askBIApiUrls格式
        if (!newLine.includes('// 原来的url:') && !url.includes('askBIApiUrls')) {
          lines[quoteLineIndex] = newLine + ` // 原来的url: ${url}`
        } else {
          lines[quoteLineIndex] = newLine
        }

        newContent = lines.join('\n')
      } else {
        if (newUrl !== url) {
          const finalRequestCall = newRequestCall.replace(url, newUrl)
          newContent = newContent.replace(fullMatch, finalRequestCall)
        } else {
          newContent = newContent.replace(fullMatch, newRequestCall)
        }
      }

      modified = true
    }

    // 添加 @ts-ignore 注释到 params 行
    const paramsRegex = /params:\s*API\.\w+/g
    let paramsMatch
    while ((paramsMatch = paramsRegex.exec(newContent)) !== null) {
      const fullParamsMatch = paramsMatch[0]
      const beforeParams = newContent.substring(0, paramsMatch.index)
      const afterParams = newContent.substring(paramsMatch.index + fullParamsMatch.length)

      // 检查前面是否已经有 @ts-ignore
      const beforeLine = beforeParams.split('\n').pop() || ''
      if (!beforeLine.trim().includes('// @ts-ignore')) {
        const newParamsLine = `  // @ts-ignore\n  ${fullParamsMatch}`
        newContent = beforeParams + newParamsLine + afterParams
        modified = true

        // 更新索引，因为内容长度发生了变化
        const lengthDiff = newParamsLine.length - fullParamsMatch.length
        paramsMatch.index += lengthDiff
      }
    }

    if (modified) {
      fs.writeFileSync(filePath, newContent, 'utf8')
    }

    return modified
  } catch (error) {
    return false
  }
}

// 提取askBIApiUrls的键值对并添加到auto-generate-without-base-url.ts
function extractAskBIApiUrlsKeyValuePairs() {
  const apiDir = path.join(__dirname, 'src', 'client', 'api')

  const targetFile = path.join(__dirname, 'src', 'shared', 'auto-generate-without-base-url.ts')

  if (!fs.existsSync(apiDir)) {
    return
  }

  if (!fs.existsSync(targetFile)) {
    return
  }

  const keyValuePairs = {}

  // 读取目录中的所有.ts文件
  const files = fs
    .readdirSync(apiDir)
    .filter((file) => file.endsWith('.ts') && file !== 'index.ts' && file !== 'typings.d.ts')

  for (const file of files) {
    const filePath = path.join(apiDir, file)
    try {
      const content = fs.readFileSync(filePath, 'utf8')

      // 匹配askBIApiUrls.xxx的调用
      const askBIApiUrlsRegex = /askBIApiUrls\.(\w+)(?:\([^)]*\))?/g
      let match

      while ((match = askBIApiUrlsRegex.exec(content)) !== null) {
        const key = match[1]
        const fullMatch = match[0]

        // 查找包含这个调用的行
        const lines = content.split('\n')
        let targetLineIndex = -1

        for (let i = 0; i < lines.length; i++) {
          if (lines[i].includes(fullMatch)) {
            targetLineIndex = i
            break
          }
        }

        if (targetLineIndex !== -1) {
          const currentLine = lines[targetLineIndex]

          // 从注释中提取原始URL
          const urlCommentMatch = currentLine.match(/\/\/ 原来的url: (.+)$/)
          if (urlCommentMatch) {
            const originalUrl = urlCommentMatch[1].trim()

            // 如果这个键还没有被添加，或者URL不同，则添加
            if (!keyValuePairs[key] || keyValuePairs[key] !== originalUrl) {
              keyValuePairs[key] = originalUrl
            }
          }
        }
      }
    } catch (error) {
      // 忽略文件读取错误
    }
  }

  // 处理URL，将包含变量的URL转换为函数形式
  const processedKeyValuePairs = {}

  for (const [key, url] of Object.entries(keyValuePairs)) {
    // 检查URL是否包含变量
    const paramMatches = url.match(/\$\{param(\d+)\}/g)

    if (paramMatches && paramMatches.length > 0) {
      // 提取所有参数
      const params = paramMatches.map((match) => {
        const paramNum = match.match(/\$\{param(\d+)\}/)[1]
        return `param${paramNum}`
      })

      // 从URL中提取HTTP方法和路径
      const urlPath = url.replace(/\/api\//, '').replace(/\$\{param\d+\}/g, '')

      // 从原始键名中提取HTTP方法
      let httpMethod = 'get' // 默认值
      if (key.startsWith('get')) httpMethod = 'get'
      else if (key.startsWith('post')) httpMethod = 'post'
      else if (key.startsWith('put')) httpMethod = 'put'
      else if (key.startsWith('delete')) httpMethod = 'delete'
      else if (key.startsWith('patch')) httpMethod = 'patch'

      // 重新生成键名，确保与processFile函数一致
      const newKey = generateKeyName(httpMethod, urlPath, params)

      // 生成参数类型字符串
      const paramTypes = params.map((param) => `${param}:string`).join(',')

      // 将URL转换为函数形式
      processedKeyValuePairs[newKey] = `(${paramTypes})=>\`${url}\``
    } else {
      // 没有变量的URL保持原样
      processedKeyValuePairs[key] = url
    }
  }

  // 读取目标文件内容
  const targetContent = fs.readFileSync(targetFile, 'utf8')

  // 生成新的内容
  let newContent = 'export const autoGenerateAskBIApiUrlsWithoutBaseUrl = {\n'

  for (const [key, value] of Object.entries(processedKeyValuePairs)) {
    if (typeof value === 'string' && value.includes('=>')) {
      // 函数形式的URL
      newContent += `  ${key}: ${value},\n`
    } else {
      // 普通字符串URL
      newContent += `  ${key}: '${value}',\n`
    }
  }

  newContent += '}'

  // 写入文件
  fs.writeFileSync(targetFile, newContent, 'utf8')
}

// 格式化文件函数
function formatFiles() {
  const { execSync } = require('child_process')

  try {
    console.log('开始格式化文件...')

    // 格式化api目录下的所有文件
    const apiDir = path.join(__dirname, 'src', 'client', 'api')
    if (fs.existsSync(apiDir)) {
      console.log('格式化api目录下的文件...')
      execSync(`npx prettier --write "${apiDir}/**/*.ts"`, { stdio: 'inherit' })
    }

    // 格式化auto-generate-without-base-url.ts文件
    const autoGenerateFile = path.join(__dirname, 'src', 'shared', 'auto-generate-without-base-url.ts')
    if (fs.existsSync(autoGenerateFile)) {
      console.log('格式化auto-generate-without-base-url.ts文件...')
      execSync(`npx prettier --write "${autoGenerateFile}"`, { stdio: 'inherit' })
    }

    console.log('格式化完成')
  } catch (error) {
    console.error('格式化过程中出现错误:', error.message)
  }
}

// 主函数
function main() {
  const apiDir = path.join(__dirname, 'src', 'client', 'api')

  if (!fs.existsSync(apiDir)) {
    process.exit(1)
  }

  // 读取目录中的所有.ts文件
  const files = fs
    .readdirSync(apiDir)
    .filter((file) => file.endsWith('.ts') && file !== 'index.ts' && file !== 'typings.d.ts')

  let totalFiles = 0
  let updatedFiles = 0

  for (const file of files) {
    const filePath = path.join(apiDir, file)
    totalFiles++

    if (processFile(filePath)) {
      updatedFiles++
    }
  }

  // 5秒后执行提取askBIApiUrls键值对的功能（原代码setTimeout延迟为0，此处保持一致）
  setTimeout(() => {
    extractAskBIApiUrlsKeyValuePairs()
    formatFiles()

    console.log('完成所有内容')

    // 格式化文件
  }, 0)
}

// 运行脚本
if (require.main === module) {
  main()
}

module.exports = { processFile, toCamelCase }
